home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1997 October / macformat-055.iso / mac / Shareware Plus / Developers / VideoToolbox / VideoToolboxSources / AtExitToShell.c < prev    next >
Encoding:
Text File  |  1997-04-10  |  7.3 KB  |  183 lines  |  [TEXT/CWIE]

  1. /*
  2. AtExitToShell.c
  3.  
  4.     void YourFunction(void);
  5.  
  6.     error=AtExitToShell(YourFunction);
  7.  
  8. AtExitToShell(YourFunction) requests that your function be called when the
  9. application quits, i.e. calls the ExitToShell trap, which tells the MacOS that
  10. it's done. Your function must have no arguments and no return value.
  11.  
  12. (MATLAB: If you compile this file as a MEX resource, to be called from MATLAB, 
  13. then your call to AtExitToShell is a request that your function be called when 
  14. the MEX resource is flushed from memory.)
  15.  
  16. Many VideoToolbox routines set up interrupt service routines that must be killed
  17. before the program goes away. We want to kill these whether we quit via exit(),
  18. abort(), or the ExitToShell trap is invoked directly, e.g. if user types "ES"
  19. in MacsBug. The only way to be sure of killing something before the application
  20. goes away is to attach its killer, by patching, to the ExitToShell trap. That's
  21. what's done here.
  22.  
  23. AtExitToShell() is closely modeled on the ANSI function atexit(). I wrote it to
  24. overcome the restrictive implementation of atexit() and _atexit() in CodeWarrior:
  25. they only invoke your functions if the ANSI function exit() is called, NOT if
  26. you call abort(), or the user types "ES" in MacsBug. I think that AtExitToShell
  27. is equivalent to the non-ANSI _atexit() routine provided by the Symantec THINK C
  28. environment.
  29.  
  30. The registration list (of user functions) is last-in, first-out. When you
  31. eventually quit, your functions will be called in reverse of the order in which
  32. you registered them. No checking is made for duplication: the same function may
  33. be registed multiple times, and will be called multiple times.
  34.  
  35. CAUTION: your application's runtime environment (e.g. stdio) will normally have
  36. shut itself down by the time it calls ExitToShell(), so a function scheduled for 
  37. that time should not assume the availability of such services (e.g. printf). 
  38. There's no restriction on the use of MacOS services.
  39.  
  40. MATLAB: the Standard C atexit() and THINK C _atexit() routines should not be 
  41. used in MATLAB code resources, because they aren't designed to handle the
  42. situation of code that may be flushed any time MATLAB executes "clear mex" or
  43. "clear all", at a time unrelated to exiting of the MATLAB application itself. 
  44. Instead, MATLAB provides mexAtExit(), which allows you to register one callback 
  45. per MEX file, which is called when the MEX file is flushed. (The problem with using
  46. mexAtExit, is that it's hard for any particular subroutine to know whether somebody
  47. else has already used up the single available slot in the call-back table.)
  48. In order to make your C subroutines as portable and autonomous as possible, you may
  49. prefer to use this AtExitToShell() which allows you to register lots of callback 
  50. routines, and registers itself, once, with mexAtExit. 
  51.  
  52. CAUTION: Since MATLAB registers only one function per MEX it is important that 
  53. you consistently adopt one strategy. Either make lots of calls to AtExitToShell
  54. (and NONE to mexAtExit), or just one call to mexAtExit. If you call both AtExitToShell
  55. and mexAtExit then one will displace the other in MATLAB's one-entry table.
  56.  
  57. CODE FRAGMENT MANAGER:
  58.  
  59. The following is quoted from C.S.M.P. Digest, Volume 4 : Issue 31, 02 Jan 97       
  60.  
  61. >From SouthSide@kagi.com (Bob Bradley)
  62. Date: Mon, 16 Dec 1996 20:53:48 -0800
  63. Organization: SPC
  64.  
  65. In article <32B57B59.566A@kp.ssdn.skelleftea.se>,
  66. JSO0605@kp.ssdn.skelleftea.se [Johan Sˆrlin, johan.sorlin@mailbox.hogia.net] wrote:
  67.  
  68. > Can anyone please tell me how to make a PPC ExitToShell Patch?
  69. > I need a PPC function of: AtExitToShell that i found in VideoToolbox.
  70.  
  71. You can use the CFM Termination routine to do what an ExitToShell patch
  72. would do for non-CFM 68K code. Otherwise, you just need to create a
  73. RoutineDescriptor to your patched ExitToShell instead of passing just a
  74. ProcPtr to SetToolTrapAddress. [That's exactly what the code below does--dgp]
  75.  
  76. Check out the Code Fragment Manager chapter in Inside Mac: PowerPC System
  77. Software. 
  78.  
  79. +++++++++++++++++++++++++++
  80. >From mxmora@mxmdesigns.com (Matthew Xavier Mora)
  81. Date: Mon, 16 Dec 1996 21:55:08 -0800
  82. Organization: MXM DesignsÅ
  83.  
  84. In article <32B57B59.566A@kp.ssdn.skelleftea.se>,
  85. JSO0605@kp.ssdn.skelleftea.se wrote:
  86.  
  87. > Can anyone please tell me how to make a PPC ExitToShell Patch?
  88. > I need a PPC function of: AtExitToShell that i found in VideoToolbox.
  89.  
  90.  
  91. Install a CFM Termination routine. In MW look in the Linker
  92. pref panel (I think). Type in the name of the routine that you 
  93. want called when your app exits.
  94.  
  95. Xavier
  96.  
  97. -- 
  98. Matthew Xavier Mora                    <mailto:mxmora@mxmdesigns.com>
  99.                                <http://www.best.com/~mxmora/mxm.html>
  100. +++++++++++++++++++++++++++
  101. [I guess anyone writing code that must run under CFM will have to
  102. figure this out. I haven't had any occasion to do so. If you figure it
  103. out, I'd appreciate a note for this file. denis@psych.nyu.edu]
  104.  
  105.  
  106. HISTORY:
  107. 10/27/94 dgp wrote the ExitToShell patch, based on examples that appeared in UseNet
  108.     csmp-digest-v3-046 by Kevin Bell (kbell@cs.utexas.edu) and Bill Hofmann
  109.     (wdh@netcom.com) in response to a query by Steve Coy (stevec@jolt.mpx.com.au)
  110. 6/17/95 dgp wrote AtExitToShell.c
  111. 7/1/95 dgp made compatible with pre-universal apple headers. 
  112.     Disable if MATLAB is true. Added comments about MATLAB. 
  113. 7/17/95 dgp made compatible with pre-universal headers
  114. 4/19/96 dgp call mexAtExit(). I know this is ok for PPC, but may not work for 68k.
  115. 6/10/96 dgp fixed initialization error when MATLAB is true.
  116. 6/10/96 dgp added a couple of paragraphs explaining its use in MATLAB MEX files.
  117. 6/11/96 dgp In response to concerns raised by David Brainard, I added text above
  118.         warning about the danger of calling BOTH AtExitToShell and mexAtExit, and
  119.         I made the A5 stuff conditional on !MATLAB.
  120. 8/5/96    dgp #undef mexAtExit to make sure we call the real McCoy.
  121. 1/9/97    dgp added csmp quote about CFM, above
  122. 4/10/97    dgp    Eliminate stuff that was conditional on !UNIVERSAL_HEADERS.
  123. */
  124. #ifndef _VIDEOTOOLBOX_
  125.     #include "VideoToolbox.h"
  126. #endif
  127. #ifndef __TRAPS__
  128.     #include <Traps.h>    // _ExitToShell
  129. #endif
  130. #include <SegLoad.h>    // ExitToShell()
  131. typedef UniversalProcPtr TrapAddressType;
  132. static pascal void MyExitToShell(void);
  133. #define FUNCTIONS 35
  134. static UniversalProcPtr oldExitToShellTrapAddress=NULL;    // save address of real ExitToShell trap.
  135. static void (*userFunction[FUNCTIONS])(void);    // table of user functions to be called at exit.
  136.  
  137. int AtExitToShell(void (*userFunctionPtr)(void))
  138. {
  139.     #if !MATLAB
  140.         UniversalProcPtr myExitToShellUPP;
  141.     #endif
  142.     int i;
  143.     static Boolean firstTime=1;
  144.  
  145.     if(firstTime){
  146.         #if !MATLAB
  147.             myExitToShellUPP=NewRoutineDescriptor((ProcPtr)MyExitToShell
  148.                 ,kPascalStackBased,GetCurrentISA());
  149.             oldExitToShellTrapAddress=(UniversalProcPtr)GetToolTrapAddress(_ExitToShell);
  150.             SetToolTrapAddress((TrapAddressType)myExitToShellUPP,_ExitToShell);
  151.         #else
  152.             // Ask MATLAB to call MyExitToShell just before disposing of our MEX resource.
  153.             #undef mexAtExit
  154.             mexAtExit((void *)MyExitToShell);
  155.         #endif
  156.         for(i=0;i<FUNCTIONS;i++)userFunction[i]=NULL;
  157.         firstTime=0;
  158.     }
  159.     for(i=0;i<FUNCTIONS;i++)if(userFunction[i]==NULL){
  160.         userFunction[i]=userFunctionPtr;
  161.         return 0;    // success
  162.     }
  163.     return 1;        // failure: the table's already full
  164. }
  165.  
  166. static pascal void MyExitToShell(void)
  167. {
  168.     int i;
  169.     
  170.     #if !MATLAB
  171.         SetCurrentA5();
  172.         SetToolTrapAddress((TrapAddressType)oldExitToShellTrapAddress,_ExitToShell);
  173.     #endif
  174.  
  175.     for(i=FUNCTIONS-1;i>=0;i--)if(userFunction[i]!=NULL){
  176.         (*userFunction[i])();
  177.     }
  178.  
  179.     #if !MATLAB
  180.         ExitToShell();
  181.     #endif
  182. }
  183.